package com.gitee.wsl.text.buffer.ext

import androidx.compose.ui.text.TextRange
import com.gitee.wsl.text.buffer.TextBuffer
import com.gitee.wsl.text.buffer.Unspecified
import com.gitee.wsl.text.buffer.storage.GetCharsTrait
import com.gitee.wsl.text.buffer.storage.TextBufferStorage
import com.gitee.wsl.text.buffer.storage.charArrayGetCharsTrait
import com.gitee.wsl.text.buffer.storage.charSequenceGetCharsTrait
import com.gitee.wsl.text.buffer.storage.getChars


fun TextBuffer.replaceCharSequence(
    range: TextRange /*= TextRange.Unspecified*/,
    replacement: CharSequence,
    replacementRange: TextRange = TextRange(0, replacement.length)
) = when (replacement) {
    is String -> replace(range, replacement, replacementRange)
    is StringBuilder -> replace(range, replacement, replacementRange)
    //is StringBuffer -> replace(range, replacement, replacementRange)
    is TextBuffer -> replace(range, replacement, replacementRange)
    is TextBufferStorage -> replace(range, replacement as TextBufferStorage, replacementRange)
    is GetCharsTrait<*> -> {
        // Assume it's self-typed.
        @Suppress("UNCHECKED_CAST")
        val trait = replacement as GetCharsTrait<CharSequence>
        replace(range, replacement, replacementRange, trait)
    }

    // Slow path if we don't have access to a getChars method.
    else -> replace(range, replacement, replacementRange, charSequenceGetCharsTrait)
}

@Suppress("NOTHING_TO_INLINE")
inline fun TextBuffer.replace(
    range: TextRange = TextRange.Companion.Unspecified,
    replacement: CharArray,
    replacementRange: TextRange = TextRange(0, replacement.size)
) = replace(range, replacement, replacementRange, charArrayGetCharsTrait)

@Suppress("NOTHING_TO_INLINE")
inline fun TextBuffer.replace(
    range: TextRange = TextRange.Unspecified,
    replacement: StringBuilder,
    replacementRange: TextRange = TextRange(0, replacement.length)
) = replace(range, replacement, replacementRange, StringBuilder::getChars)


@Suppress("NOTHING_TO_INLINE")
inline fun TextBuffer.replace(
    range: TextRange = TextRange.Unspecified,
    replacement: String,
    replacementRange: TextRange = TextRange(0, replacement.length)
) {
    @Suppress("UNCHECKED_CAST")
    replace(
        range,
        replacement,
        replacementRange,
        String::getChars as GetCharsTrait<String>
    )
}

@Suppress("NOTHING_TO_INLINE")
inline fun TextBuffer.replace(
    range: TextRange = TextRange.Unspecified,
    replacement: TextBuffer,
    replacementRange: TextRange = TextRange(0, replacement.length)
) = replace(range, replacement, replacementRange, GetCharsTrait.Companion.TextBuffer)


@Suppress("NOTHING_TO_INLINE")
inline fun TextBuffer.replace(
    range: TextRange = TextRange.Unspecified,
    replacement: TextBufferStorage,
    replacementRange: TextRange = TextRange(0, replacement.length)
) = replace(range, replacement, replacementRange, TextBufferStorage)

@Suppress("NOTHING_TO_INLINE")
inline fun <T> TextBuffer.replace(
    range: TextRange = TextRange.Unspecified,
    replacement: T,
    replacementRange: TextRange = TextRange(0, replacement.length)
) where T : CharSequence, T : GetCharsTrait<T> =
    replace(range, replacement, replacementRange, replacement)